#ifndef _BLOCKBREAKER_COMM_SYNCQUEUE_H__
#define _BLOCKBREAKER_COMM_SYNCQUEUE_H__

// STL
#include <queue>

// Utils
#include <Comm/Include/ISincronizable.h>
#include <Comm/Include/Semaphore.h>
#include <Comm/Include/SimpleMessage.h>

typedef void (*TCallbackAsyncReceiveFunction)(SimpleMessage* msg, void* user_data);

class SyncQueue : public ISincronizable
{
    public:
        typedef enum
        {
            QUEUE_ALREADY_CLOSED,
            FRONT_TIMEOUT,
            POP_TIMEOUT
        }SyncQueueExceptionType;

        SyncQueue(void);

        virtual ~SyncQueue(void);

        void push(SimpleMessage* msg);

        SimpleMessage* pop(unsigned int timeout = 0);

        SimpleMessage* front(unsigned int timeout = 0);

        void installAsyncReceiveFunction(TCallbackAsyncReceiveFunction f, void* user_data);

        void* uninstallAsyncReceiveFunction();

        void closeAndWaitTillEmpty();

        void closeAndDiscardAll();

        void close();

    private:
        std::queue<SimpleMessage*> cola;

        TCallbackAsyncReceiveFunction async_recv_func;

        void* asyn_func_user_data;

        Semaphore* semaphore;
    
        // attributes used to close the queue and wait till it is empty
        bool fin_cerrada;

        Semaphore* fin_sem;

        bool releasing_thread_on_pop;
};
#endif // _BLOCKBREAKER_COMM_SYNCQUEUE_H__
